// Random useful stuff

#ifndef game_core_h
#define game_core_h

#include <iostream>
#include <string>
#include <OpenGL/gl.h>

// Size of screen.
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;

// Some useful asserts
#define CHECK(a) do { if (!(a)) { std::cout << "CHECK FAILED: " << #a << "\n"; exit(1); } } while(0)
#define CHECK_EQ(a, b) do { if ((a) != (b)) { std::cout << "CHECK FAILED: " << #a << " != " << #b << "\n"; exit(1); } } while(0)

// The number of elements in a c array.
#define N_ELEMS(a) ((sizeof(a)) / sizeof(a[0]))

// Useful constants.
const double CONST_PI = 3.141592654;
const double CONST_TWOPI = 2 * 3.141592654;

// Where game resources can be found.
inline std::string resource_dir() {
    return "./resources";
}

// A 32-bit unsigned value. Used for colors.
typedef unsigned int u32;
typedef unsigned char u8;

inline int CLAMP(int x, int min_x, int max_x) {
    return (x < min_x) ? min_x : (x > max_x) ? max_x: x;
}

// Create an RGBA color.
inline u32 RGBA(int r, int g, int b, int a) {
    return (u8(CLAMP(r, 0, 255)) << 24) | (u8(CLAMP(g, 0, 255)) << 16) | (u8(CLAMP(b, 0, 255)) << 8) | u8(CLAMP(a, 0, 255));
}

// Create an RGB color.
inline u32 RGB(int r, int g, int b) { return RGBA(r, g, b, 255); }

// Extract R, G, B or A from a color.
inline u8 R(u32 rgba) { return (rgba >> 24) & 0xff; }
inline u8 G(u32 rgba) { return (rgba >> 16) & 0xff; }
inline u8 B(u32 rgba) { return (rgba >> 8) & 0xff; }
inline u8 A(u32 rgba) { return rgba & 0xff; }

// Set the GL color.
inline void SetColor(u32 c) {
    glColor4ub(R(c), G(c), B(c), A(c));
}

// Multiply componentwise two colors.
inline u32 COL_MUL(u32 c0, u32 c1) {
    return RGBA(R(c0) * R(c1) / 256, G(c0) * G(c1) / 256,
                B(c0) * B(c1) / 256, A(c0) * A(c1) / 256);
}

const u32 COL_WHITE = 0xffffffff;
const u32 COL_MUSTARD = 0xc49b64ff;
const u32 COL_BLACK = 0x000000ff;

#endif
